home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 1.iso / desktop / dibquant.zip / DIBQUANT.C next >
C/C++ Source or Header  |  1994-06-17  |  24KB  |  864 lines

  1. ///////////////////////////////////////////////////////////////////////////
  2. // DIBQuant version 1.0
  3. // Copyright (c) 1993 Edward McCreary.
  4. // All rights reserved.
  5. //
  6. // Redistribution and use in source and binary forms are freely permitted
  7. // provided that the above copyright notice and attibution and date of work
  8. // and this paragraph are duplicated in all such forms.
  9. // THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
  10. // IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  11. // WARRANTIES OF MERCHANTIBILILTY AND FITNESS FOR A PARTICULAR PURPOSE.
  12. ///////////////////////////////////////////////////////////////////////////
  13. #define STRICT
  14. #include <windows.h>
  15. #include <windowsx.h>
  16. #include <limits.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <memory.h>
  20.  
  21. #include "dibquant.h"
  22. #include "rgbvtab.h"
  23. #include "local.h"
  24. #include "palette.h"
  25.  
  26. ///////////////////////////////////////////////////////////////////////////
  27. // ordered dither matrix
  28. int     ord_dith[4][4] = {{-7,  1, -5,  3},
  29.               { 5, -3,  7, -1},
  30.               {-4,  4, -6,  2},
  31.               { 8,  0,  6, -2}};
  32.  
  33.  
  34. // instance handle of dll
  35. HINSTANCE hInst;
  36.  
  37. ///////////////////////////////////////////////////////////////////////////
  38. // Main DLL Entry Point
  39. BOOL WINAPI LibMain (HINSTANCE hInstance, WORD wDataSeg,
  40.     WORD wHeapSize, LPSTR lpszCmdLine)
  41.  {
  42.   if(wHeapSize != 0)
  43.    UnlockData(0);
  44.  
  45.   hInst = hInstance;
  46.   return (TRUE);
  47.  }
  48.  
  49. ///////////////////////////////////////////////////////////////////////////
  50. // Exit procedure for DLL
  51. int WINAPI WEP(int nSystemExit)
  52.  {
  53.   switch(nSystemExit)
  54.   {
  55.    case WEP_SYSTEM_EXIT:
  56.     break;
  57.    case WEP_FREE_DLL:
  58.     break;
  59.    }
  60.    return (1);
  61.  }
  62.  
  63. ///////////////////////////////////////////////////////////////////////////
  64. // build buffer space and lookup table
  65. LPQUANT_BUFFER InitLUT()
  66. {
  67.  LPQUANT_BUFFER lpBuffer;
  68.  unsigned long i; 
  69.  unsigned long len;
  70.  
  71.  lpBuffer = (LPQUANT_BUFFER)malloc(sizeof(QUANT_BUFFER));
  72.  if(!lpBuffer)
  73.   return NULL;
  74.   
  75.  // lut for x^2
  76.  for(i=0;i<256;i++)
  77.   lpBuffer->SQR[i] = (long)i*(long)i;
  78.  
  79.  len = (long)COLOR_MAX*(long)COLOR_MAX*(long)COLOR_MAX;
  80.  
  81.  // buffer to store every color in image
  82.  lpBuffer->lpHisto = (LPNode huge *)GlobalAllocPtr(GHND,len*sizeof(LPNode));
  83.  
  84.  return lpBuffer;
  85. }
  86.  
  87. ///////////////////////////////////////////////////////////////////////////
  88. // free memory associated with buffers and luts
  89. void ClearLUT(LPQUANT_BUFFER lpBuffers)
  90.  unsigned long len = (long)COLOR_MAX*(long)COLOR_MAX*(long)COLOR_MAX;
  91.  unsigned long i;
  92.  
  93.  if(lpBuffers->lpHisto)
  94.  {
  95.   for(i=0;i<len;i++)
  96.    if(lpBuffers->lpHisto[i] != NULL)
  97.    {
  98.     free(lpBuffers->lpHisto[i]);
  99.     lpBuffers->lpHisto[i] = NULL;
  100.    } 
  101.   GlobalFreePtr((LPSTR)lpBuffers->lpHisto);  
  102.  }
  103.  free(lpBuffers);
  104. }
  105.  
  106.  
  107. ///////////////////////////////////////////////////////////////////////////
  108. // main procedures, quantize 24-bit dib
  109. LPSTR FAR PASCAL __export QuantizeDIB(LPSTR lpDIB, int nPalette, int nDither,FARPROC lpStatus)
  110. {
  111.  long width,height;
  112.  LPBITMAPINFOHEADER lpbmi;
  113.  LPSTR lpData;
  114.  BYTE huge *lpLine;
  115.  long i,j;
  116.  int r,g,b;
  117.  long dib_width;
  118.  LPSTR lpNewDIB;
  119.  char buffer[80];
  120.  LPQUANT_BUFFER lpBuffer;
  121.  
  122.  // must have adib
  123.  if(!lpDIB)
  124.   return NULL; 
  125.  
  126.  // must be a 24-bit dib
  127.  lpbmi = (LPBITMAPINFOHEADER)lpDIB;
  128.  if(lpbmi->biBitCount != 24)
  129.   return NULL;
  130.  
  131.  // allocate buffers
  132.  lpBuffer = InitLUT();
  133.   if(!lpBuffer)
  134.    return NULL;
  135.  
  136.  // store handle to status indicator callback
  137.  lpBuffer->lpStatus = lpStatus;
  138.   
  139.  width = lpbmi->biWidth;
  140.  height = lpbmi->biHeight;
  141.  dib_width = WIDTHBYTES(24*width);
  142.  
  143.  lpData = FindDIBBits(lpDIB); 
  144.  
  145.  // generate list of all colors if needed      
  146.  if(nPalette != IDX_DEFAULT)      
  147.   for(j=0;j<height;j++)
  148.    {
  149.     lpLine = (BYTE huge *)lpData + dib_width*j;
  150.     i = width;
  151.     if(lpBuffer->lpStatus)
  152.     {
  153.      wsprintf(buffer,"Finding all colors, %d%%",(int)(100.0*((float)j/(float)height)));
  154.      ((STATUS_CAST)lpBuffer->lpStatus)(buffer);
  155.     } 
  156.     while(i--)
  157.     {
  158.      b = (int)*lpLine++;    
  159.      g = (int)*lpLine++;    
  160.      r = (int)*lpLine++;    
  161.      
  162.     add_color(r>>3,g>>3,b>>3,1L,lpBuffer);    
  163.     }  
  164.    }
  165.  
  166.  // call status if needed
  167.  if(lpBuffer->lpStatus)
  168.      ((STATUS_CAST)lpBuffer->lpStatus)("Building new palette...");
  169.  
  170.  switch(nPalette)
  171.  {
  172.   case IDX_MEDIAN:
  173.    m_box(lpBuffer);
  174.   break;
  175.   
  176.   case IDX_POPULARITY:
  177.    pop(lpBuffer);
  178.   break;
  179.   
  180.   case IDX_DEFAULT:
  181.    LoadDefaultPal(lpBuffer);
  182.   break;
  183.   
  184.   default:
  185.    m_box(lpBuffer);
  186.   break;  
  187.  }
  188.  
  189.  lpNewDIB = Dither(lpDIB,nDither,lpBuffer);
  190.  
  191.  ClearLUT(lpBuffer);
  192.  
  193.  return lpNewDIB; 
  194. }
  195.  
  196.  
  197. ///////////////////////////////////////////////////////////////////////////
  198. // dither image
  199. LPSTR __export Dither(LPSTR lpDIB,int nDither,LPQUANT_BUFFER lpBuffer)
  200. {
  201.  LPSTR lpNewDIB;
  202.  LPSTR lpSrcData;
  203.  LPSTR lpDestData;
  204.  long src_dib_width,dest_dib_width;
  205.  LPBITMAPINFOHEADER  lpbmih;
  206.  long width,height;
  207.  BYTE huge *lpSrcLine;
  208.  BYTE huge *lpDestLine;
  209.  long i,j;
  210.  char buffer[80];
  211.  int r,g,b;
  212.  
  213.  lpNewDIB = AllocNewDIB(lpDIB,lpBuffer);
  214.  if(!lpNewDIB)
  215.   return NULL; 
  216.  
  217.  lpSrcData =  FindDIBBits(lpDIB); 
  218.  lpDestData = FindDIBBits(lpNewDIB); 
  219.  
  220.  
  221.  lpbmih = (LPBITMAPINFOHEADER)lpDIB;
  222.  if(lpbmih->biBitCount != 24)
  223.   return NULL;
  224.   
  225.  width = lpbmih->biWidth;
  226.  height = lpbmih->biHeight;
  227.  src_dib_width = WIDTHBYTES(24*width);
  228.  dest_dib_width = WIDTHBYTES(8*width); 
  229.   
  230.   for(j=0;j<height;j++)
  231.    {
  232.     lpSrcLine = (BYTE huge *)lpSrcData + src_dib_width*j;
  233.     lpDestLine = (BYTE huge *)lpDestData + dest_dib_width*j;
  234.     
  235.     if(lpBuffer->lpStatus)
  236.     {
  237.      wsprintf(buffer,"Building new Image, %d%%",(int)(100.0*((float)j/(float)height)));
  238.      ((STATUS_CAST)lpBuffer->lpStatus)(buffer);
  239.     } 
  240.     
  241.     i = width;
  242.     while(i--)
  243.     {    
  244.      b = (int)*lpSrcLine++;     
  245.      g = (int)*lpSrcLine++;     
  246.      r = (int)*lpSrcLine++;     
  247.      
  248.      if(nDither == IDX_JITTER)
  249.       jitter(i,j,&r,&g,&b);
  250.      
  251.      if(nDither == IDX_ORDERED)
  252.      { 
  253.       r += 2*ord_dith[i%4][j%4]; r = CLIP(r); 
  254.       g += 2*ord_dith[i%4][j%4]; g = CLIP(g); 
  255.       b += 2*ord_dith[i%4][j%4]; b = CLIP(b); 
  256.      }
  257.           
  258.      *lpDestLine++ = (BYTE)GetNeighbor(r,g,b,lpBuffer);     
  259.     }  
  260.    }   
  261.    
  262.    if(lpBuffer->lpStatus)
  263.    {
  264.     wsprintf(buffer,"Building new Image, 100%%");
  265.     ((STATUS_CAST)lpBuffer->lpStatus)(buffer);
  266.    } 
  267.  
  268.  return lpNewDIB;
  269. }
  270.  
  271. ///////////////////////////////////////////////////////////////////////////
  272. // build new palette with median cut algorithm
  273. // I didn't write this, if you know who did, please let me know!
  274. void __export m_box(LPQUANT_BUFFER lpBuffer)
  275. {
  276.     int     i, j, max, dr, dg, db;    
  277.     char buffer[80];
  278.     /* force the counts in the corners to be zero */
  279.  
  280.     force( 0,  0,  0, 0L,lpBuffer);
  281.     force(COLOR_MAX-1,  0,  0, 0L,lpBuffer);
  282.     force( 0, COLOR_MAX-1,  0, 0L,lpBuffer);
  283.     force( 0,  0, COLOR_MAX-1, 0L,lpBuffer);
  284.     force(COLOR_MAX-1, COLOR_MAX-1,  0, 0L,lpBuffer);
  285.     force( 0, COLOR_MAX-1, COLOR_MAX-1, 0L,lpBuffer);
  286.     force(COLOR_MAX-1,  0, COLOR_MAX-1, 0L,lpBuffer);
  287.     force(COLOR_MAX-1, COLOR_MAX-1, COLOR_MAX-1, 0L,lpBuffer);
  288.  
  289.     /* assign the 1st eight boxes to be the corners */
  290.     make_box( 0,  0,  0, 0, 1L,lpBuffer);
  291.     make_box(COLOR_MAX-1,  0,  0, 1, 1L,lpBuffer);
  292.     make_box( 0, COLOR_MAX-1,  0, 2, 1L,lpBuffer);
  293.     make_box( 0,  0, COLOR_MAX-1, 3, 1L,lpBuffer);
  294.     make_box(COLOR_MAX-1, COLOR_MAX-1,  0, 4, 1L,lpBuffer);
  295.     make_box( 0, COLOR_MAX-1, COLOR_MAX-1, 5, 1L,lpBuffer);
  296.     make_box(COLOR_MAX-1,  0, COLOR_MAX-1, 6, 1L,lpBuffer);
  297.     make_box(COLOR_MAX-1, COLOR_MAX-1, COLOR_MAX-1, 7, 1L,lpBuffer);
  298.  
  299.     /* set up 9th box to hold the rest of the world */
  300.     lpBuffer->box[8].r0 = 0;
  301.     lpBuffer->box[8].r1 = COLOR_MAX-1;
  302.     lpBuffer->box[8].g0 = 0;
  303.     lpBuffer->box[8].g1 = COLOR_MAX-1;
  304.     lpBuffer->box[8].b0 = 0;
  305.     lpBuffer->box[8].b1 = COLOR_MAX-1;
  306.     squeeze(8,lpBuffer);
  307.  
  308.     /* split the rest of the boxes */
  309.  
  310.     for(i=9; i<256; i++)    
  311.     {
  312.     
  313.      if(lpBuffer->lpStatus)
  314.      {
  315.       wsprintf(buffer,"splitting box %d",i);
  316.       ((STATUS_CAST)lpBuffer->lpStatus)(buffer);
  317.      }     
  318.      
  319.         /* find biggest box */
  320.         max = 8;
  321.         for(j=8; j<i; j++)
  322.             if(lpBuffer->box[j].count > lpBuffer->box[max].count)
  323.                 max = j;
  324.  
  325.         /* decide which side to split the box along, and split it */
  326.  
  327.         dr = lpBuffer->box[max].r1 - lpBuffer->box[max].r0;
  328.         dg = lpBuffer->box[max].g1 - lpBuffer->box[max].g0;
  329.         db = lpBuffer->box[max].b1 - lpBuffer->box[max].b0;
  330.         lpBuffer->box[i] = lpBuffer->box[max];              /* copy info over */
  331.         if(dr>=dg && dr>=db) 
  332.         {          /* red! */
  333.             if(dr==2) 
  334.             {             /* tight squeeze */
  335.                 lpBuffer->box[i].r1 = lpBuffer->box[i].r0;
  336.                 lpBuffer->box[max].r0 = lpBuffer->box[max].r1;
  337.             } else 
  338.             {                /* figure out where to split */
  339.                 j = lpBuffer->box[max].rave;
  340.                 if(j==lpBuffer->box[max].r1)
  341.                     j--;
  342.                 lpBuffer->box[max].r1 = j;
  343.                 lpBuffer->box[i].r0 = j+1;
  344.             }
  345.             squeeze(i,lpBuffer);
  346.             squeeze(max,lpBuffer);
  347.         } 
  348.         else if(dg>=db) 
  349.         {             /* green! */
  350.             if(dg==2) 
  351.             {             /* tight squeeze */
  352.                 lpBuffer->box[i].g1 = lpBuffer->box[i].g0;
  353.                 lpBuffer->box[max].g0 = lpBuffer->box[max].g1;
  354.             } 
  355.             else 
  356.             {                /* figure out where to split */
  357.                 j = lpBuffer->box[max].gave;
  358.                 if(j==lpBuffer->box[max].g1)
  359.                     j--;
  360.                 lpBuffer->box[max].g1 = j;
  361.                 lpBuffer->box[i].g0 = j+1;
  362.             }
  363.             squeeze(i,lpBuffer);
  364.             squeeze(max,lpBuffer);
  365.         } 
  366.         else 
  367.         {                        /* blue! */
  368.             if(db==2) 
  369.             {             /* tight squeeze */
  370.                 lpBuffer->box[i].b1 = lpBuffer->box[i].b0;
  371.                 lpBuffer->box[max].b0 = lpBuffer->box[max].b1;
  372.             } 
  373.             else 
  374.             {                /* figure out where to split */
  375.                 j = lpBuffer->box[max].bave;
  376.                 if(j==lpBuffer->box[max].b1)
  377.                     j--;
  378.                 lpBuffer->box[max].b1 = j;
  379.                 lpBuffer->box[i].b0 = j+1;
  380.             }
  381.             squeeze(i,lpBuffer);
  382.             squeeze(max,lpBuffer);
  383.         }
  384.  
  385.     }       /* end of i loop, all the boxes are found */
  386.  
  387.     /* get palette colors for each box */
  388.     for(i=0; i<256; i++) 
  389.     {
  390.          lpBuffer->red[i] = (lpBuffer->box[i].r0+lpBuffer->box[i].r1)/2;
  391.          lpBuffer->green[i] = (lpBuffer->box[i].g0+lpBuffer->box[i].g1)/2;
  392.          lpBuffer->blue[i] = (lpBuffer->box[i].b0+lpBuffer->box[i].b1)/2;
  393.     }
  394.     for(i=0; i<256; i++)
  395.     {
  396.      lpBuffer->red[i] *= 255;
  397.      lpBuffer->red[i] /= (COLOR_MAX-1);
  398.      lpBuffer->green[i] *= 255;
  399.      lpBuffer->green[i] /= (COLOR_MAX-1);
  400.      lpBuffer->blue[i] *= 255;
  401.      lpBuffer->blue[i] /= (COLOR_MAX-1);
  402.     }
  403. }       /* end of m_box() */
  404.  
  405. ///////////////////////////////////////////////////////////////////////////
  406. // make a 1x1x1 box at index with color rgb count c
  407. void make_box(int r, int g, int b, int index, unsigned long c,LPQUANT_BUFFER lpBuffer)
  408. {
  409.     lpBuffer->box[index].r0 = r;
  410.     lpBuffer->box[index].r1 = r;
  411.     lpBuffer->box[index].g0 = g;
  412.     lpBuffer->box[index].g1 = g;
  413.     lpBuffer->box[index].b0 = b;
  414.     lpBuffer->box[index].b1 = b;
  415.     lpBuffer->box[index].count = c;
  416. }       /* end of make_box
  417.  
  418. /*
  419.     squeeze -- shrink a boxes extremes to fit tightly
  420.  
  421.            if a box is 1x1x1 change its count to 1
  422. */
  423.  
  424. ///////////////////////////////////////////////////////////////////////////
  425. //
  426. void squeeze(int b,LPQUANT_BUFFER lpBuffer)
  427. {
  428.     int     r0, r1, g0, g1, b0, b1;
  429.     long    i, j, k;
  430.     unsigned long count = 0;
  431.     LPNode    ptr;
  432.     DWORD index;
  433.  
  434.     r0 = lpBuffer->box[b].r0;
  435.     r1 = lpBuffer->box[b].r1;
  436.     g0 = lpBuffer->box[b].g0;
  437.     g1 = lpBuffer->box[b].g1;
  438.     b0 = lpBuffer->box[b].b0;
  439.     b1 = lpBuffer->box[b].b1;
  440.  
  441.     lpBuffer->box[b].r0 = COLOR_MAX-1; lpBuffer->box[b].r1 = 0;
  442.     lpBuffer->box[b].g0 = COLOR_MAX-1; lpBuffer->box[b].g1 = 0;
  443.     lpBuffer->box[b].b0 = COLOR_MAX-1; lpBuffer->box[b].b1 = 0;
  444.     lpBuffer->box[b].rave = 0;
  445.     lpBuffer->box[b].gave = 0;
  446.     lpBuffer->box[b].bave = 0;
  447.  
  448.     for(i=r0; i<=r1; i++)
  449.         for(j=g0; j<=g1; j++) 
  450.             for(k=b0; k<=b1; k++) 
  451.             {    
  452.              index = INDEX(i,j,k);
  453.              ptr = lpBuffer->lpHisto[index];
  454.              if(ptr) 
  455.                if(ptr->count>0L) 
  456.                 {
  457.                  lpBuffer->box[b].r0 = MIN(i, lpBuffer->box[b].r0);
  458.                  lpBuffer->box[b].r1 = MAX(i, lpBuffer->box[b].r1);
  459.                  lpBuffer->box[b].g0 = MIN(j, lpBuffer->box[b].g0);
  460.                  lpBuffer->box[b].g1 = MAX(j, lpBuffer->box[b].g1);
  461.                  lpBuffer->box[b].b0 = MIN(k, lpBuffer->box[b].b0);
  462.                  lpBuffer->box[b].b1 = MAX(k, lpBuffer->box[b].b1);
  463.                  lpBuffer->box[b].rave += (unsigned long)i * (unsigned long)ptr->count;
  464.                  lpBuffer->box[b].gave += (unsigned long)j * (unsigned long)ptr->count;
  465.                  lpBuffer->box[b].bave += (unsigned long)k * (unsigned long)ptr->count;
  466.                  count += (unsigned long)ptr->count;
  467.                  }
  468.             }
  469.     /* box is now shrunk */
  470.  
  471.     if(count) 
  472.     {
  473.         lpBuffer->box[b].rave /= count;
  474.         lpBuffer->box[b].gave /= count;
  475.         lpBuffer->box[b].bave /= count;
  476.     }
  477.  
  478.     lpBuffer->box[b].count = MIN(count, COUNT_LIMIT);
  479.  
  480.     if(lpBuffer->box[b].r0 == lpBuffer->box[b].r1 &&
  481.        lpBuffer->box[b].g0 == lpBuffer->box[b].g1 &&
  482.        lpBuffer->box[b].b0 == lpBuffer->box[b].b1) 
  483.     {    /* box is min size */
  484.         lpBuffer->box[b].count = 1L;       /* so it won't get split again */
  485.     }
  486.  
  487. }       /* end of squeeze */
  488.  
  489. ///////////////////////////////////////////////////////////////////////////
  490. //
  491. void add_color(int r, int g, int b, unsigned long c,LPQUANT_BUFFER lpBuffer)
  492. {
  493.     LPNode    ptr;
  494.     unsigned long      ltmp;
  495.     
  496.     DWORD index = INDEX(r,g,b);
  497.     c = MIN(c,COUNT_LIMIT);
  498.     if((ptr = lpBuffer->lpHisto[index]) == NULL)  // new color
  499.     {
  500.       ptr = lpBuffer->lpHisto[index] = (Node *)malloc(sizeof(Node));
  501.       ptr->index = -1;
  502.       ptr->count = c;
  503.     }
  504.     else
  505.     {    
  506.      ltmp = ptr->count;
  507.      ltmp += c;
  508.      ptr->count = MIN(ltmp,COUNT_LIMIT);
  509.     }
  510.     
  511. }       /* end of add_color()*/
  512.  
  513. ///////////////////////////////////////////////////////////////////////////
  514. //
  515. void force(int r, int g, int b, unsigned long c,LPQUANT_BUFFER lpBuffer)
  516. {
  517.     LPNode    ptr;
  518.     DWORD     index;
  519.     
  520.     c = MIN(c,COUNT_LIMIT);    
  521.     index = INDEX(r,g,b);
  522.     
  523.     if((ptr = lpBuffer->lpHisto[index]) == NULL)  // new color
  524.     {
  525.       ptr = lpBuffer->lpHisto[index] = (Node *)malloc(sizeof(Node));
  526.       ptr->index = -1; 
  527.       ptr->count = 0L;
  528.     }
  529.     
  530.     ptr->count = c;
  531.  
  532. }       /* end of force()*/
  533.  
  534.  
  535.  
  536. ///////////////////////////////////////////////////////////////////////////
  537. // popularity sort
  538. void pop(LPQUANT_BUFFER lpBuffer)
  539. {
  540.     int             i, r, g,b;
  541.     LPNode            ptr;
  542.     unsigned long    pal[256];
  543.     DWORD            index;
  544.     DWORD            index_cache = (DWORD)-1;
  545.     LPNode         ptr_cache;
  546.     
  547.     memset(pal,0,sizeof(unsigned long)*256);
  548.     
  549.     /* force corners of rgb color cube out of the running */
  550.     add_color( 0,  0,  0, 0L,lpBuffer);
  551.     add_color(COLOR_MAX-1,  0,  0, 0L,lpBuffer);
  552.     add_color( 0, COLOR_MAX-1,  0, 0L,lpBuffer);
  553.     add_color( 0,  0, COLOR_MAX-1, 0L,lpBuffer);
  554.     add_color(COLOR_MAX-1, COLOR_MAX-1,  0, 0L,lpBuffer);
  555.     add_color( 0, COLOR_MAX-1, COLOR_MAX-1, 0L,lpBuffer);
  556.     add_color(COLOR_MAX-1,  0, COLOR_MAX-1, 0L,lpBuffer);
  557.     add_color(COLOR_MAX-1, COLOR_MAX-1, COLOR_MAX-1, 0L,lpBuffer);
  558.  
  559.     /* force feed the corners into the palette */
  560.     lpBuffer->red[0] =  0; lpBuffer->green[0] =  0; lpBuffer->blue[0] =  0;
  561.     lpBuffer->red[1] = COLOR_MAX-1; lpBuffer->green[1] =  0; lpBuffer->blue[1] =  0;
  562.     lpBuffer->red[2] =  0; lpBuffer->green[2] = COLOR_MAX-1; lpBuffer->blue[2] =  0;
  563.     lpBuffer->red[3] =  0; lpBuffer->green[3] =  0; lpBuffer->blue[3] = COLOR_MAX-1;
  564.     lpBuffer->red[4] = COLOR_MAX-1; lpBuffer->green[4] = COLOR_MAX-1; lpBuffer->blue[4] =  0;
  565.     lpBuffer->red[5] =  0; lpBuffer->green[5] = COLOR_MAX-1; lpBuffer->blue[5] = COLOR_MAX-1;
  566.     lpBuffer->red[6] = COLOR_MAX-1; lpBuffer->green[6] =  0; lpBuffer->blue[6] = COLOR_MAX-1;
  567.     lpBuffer->red[7] = COLOR_MAX-1; lpBuffer->green[7] = COLOR_MAX-1; lpBuffer->blue[7] = COLOR_MAX-1;
  568.     
  569.     
  570.     for(r=0; r<COLOR_MAX; r++)
  571.     {
  572.         for(g=0; g<COLOR_MAX; g++) 
  573.             for(b=0; b<COLOR_MAX; b++) 
  574.             {             
  575.              index = INDEX(r,g,b);
  576.              if(index == index_cache)
  577.               ptr = ptr_cache;
  578.              else
  579.              {
  580.               ptr = lpBuffer->lpHisto[index];
  581.               ptr_cache = ptr;
  582.               index_cache = index;
  583.              }
  584.              
  585.              if(ptr != NULL) 
  586.              {
  587.                 if(ptr->count > pal[255]) 
  588.                 {
  589.                     pal[255] = ptr->count;
  590.                     lpBuffer->red[255] = r;
  591.                     lpBuffer->green[255] = g;
  592.                     lpBuffer->blue[255] = b;
  593.  
  594.                     i = 255;        /* bubble up */
  595.                     while(pal[i]>pal[i-1] && i>8) 
  596.                     {
  597.                         SWAP(pal[i], pal[i-1]);
  598.                         SWAP(lpBuffer->red[i], lpBuffer->red[i-1]);
  599.                         SWAP(lpBuffer->green[i], lpBuffer->green[i-1]);
  600.                         SWAP(lpBuffer->blue[i], lpBuffer->blue[i-1]);
  601.                         i--;
  602.                     }
  603.                 }
  604.                 
  605.              }       /* end of current chain */
  606.             }       /* end of r loop */            
  607.     }    
  608.     for(i=0; i<256; i++)
  609.     {
  610.      lpBuffer->red[i] *= 255;
  611.      lpBuffer->red[i] /= (COLOR_MAX-1);
  612.      lpBuffer->green[i] *= 255;
  613.      lpBuffer->green[i] /= (COLOR_MAX-1);
  614.      lpBuffer->blue[i] *= 255;
  615.      lpBuffer->blue[i] /= (COLOR_MAX-1);
  616.     }
  617.    
  618. }       /* end of pop */
  619.  
  620.  
  621. ///////////////////////////////////////////////////////////////////////////
  622. //
  623. LPSTR AllocNewDIB(LPSTR lpDIB,LPQUANT_BUFFER lpBuffer)
  624. {
  625.  long width,height;
  626.  LPBITMAPINFOHEADER lpbmih;
  627.  LPBITMAPINFO       lpbmi; 
  628.  long i;
  629.  long dest_dib_width;
  630.  LPSTR lpNewDIB;
  631.  DWORD dwSize;
  632.  
  633.  if(!lpDIB)
  634.   return NULL; 
  635.  
  636.  lpbmih = (LPBITMAPINFOHEADER)lpDIB;
  637.  if(lpbmih->biBitCount != 24)
  638.   return NULL;
  639.   
  640.  width = lpbmih->biWidth;
  641.  height = lpbmih->biHeight; 
  642.  dest_dib_width = WIDTHBYTES(8*width); 
  643.  
  644.  dwSize = dest_dib_width*height + ((long)sizeof(BITMAPINFOHEADER) + 
  645.     (long)(256 * sizeof(RGBQUAD)));
  646.  
  647.  lpNewDIB = (LPSTR)GlobalAllocPtr(GHND | GMEM_SHARE,dwSize);
  648.  
  649.  if(!lpNewDIB)
  650.   return NULL;
  651.   
  652.  lpbmih = (LPBITMAPINFOHEADER)lpNewDIB;
  653.  lpbmih->biSize         = sizeof(BITMAPINFOHEADER);
  654.  lpbmih->biWidth        = (DWORD)width;
  655.  lpbmih->biHeight       = (DWORD)height;
  656.  lpbmih->biPlanes       = 1;
  657.  lpbmih->biBitCount     = 8;
  658.  lpbmih->biCompression  = BI_RGB;
  659.  lpbmih->biSizeImage    = (DWORD)dwSize;
  660.  lpbmih->biClrUsed      = 256;
  661.  lpbmih->biClrImportant = 256;
  662.  
  663.  lpbmi = (LPBITMAPINFO)lpNewDIB;
  664.  for(i=0;i<256;i++)
  665.  {
  666.   lpbmi->bmiColors[i].rgbBlue = (BYTE)(lpBuffer->blue[i]);
  667.   lpbmi->bmiColors[i].rgbGreen = (BYTE)(lpBuffer->green[i]);
  668.   lpbmi->bmiColors[i].rgbRed = (BYTE)(lpBuffer->red[i]);
  669.   lpbmi->bmiColors[i].rgbReserved = (BYTE)0;
  670.  }
  671.  
  672.  return lpNewDIB;
  673. }
  674.  
  675. ///////////////////////////////////////////////////////////////////////////
  676. //
  677. int GetNeighbor(int r,int g,int b,LPQUANT_BUFFER lpBuffer)
  678. {
  679.  int bReturn; 
  680.  
  681.   DWORD  index = 0;
  682.   long min_dist = 0;
  683.   long dist = 0;
  684.   int  c;
  685.   int dr,dg,db;
  686.   int i,j,k; 
  687.   LPNode ptr;
  688.   
  689.   index = INDEX((r>>3),(g>>3),(b>>3));
  690.   if( (ptr = lpBuffer->lpHisto[index]) == NULL)
  691.   {
  692.    lpBuffer->lpHisto[index] = ptr = (Node *)malloc(sizeof(Node));
  693.    ptr->count = 0L;
  694.    ptr->index = -1;
  695.   }
  696.   
  697.   if( (bReturn = ptr->index) == -1)
  698.   {   
  699.    ptr->index = 0;
  700.    i = lpBuffer->red[0];
  701.    j = lpBuffer->green[0];
  702.    k = lpBuffer->blue[0];
  703.  
  704.    dr = i - r;
  705.    dg = j - g;
  706.    db = k - b;
  707.    min_dist = lpBuffer->SQR[abs(dr)] + lpBuffer->SQR[abs(dg)] + lpBuffer->SQR[abs(db)];
  708.    
  709.    for(c = 1;c<256;c++)
  710.    {
  711.     i = lpBuffer->red[c];
  712.     j = lpBuffer->green[c];
  713.     k = lpBuffer->blue[c];
  714.    
  715.     dr = i - r;
  716.     dg = j - g;
  717.     db = k - b;   
  718.     dist = lpBuffer->SQR[abs(dr)] + lpBuffer->SQR[abs(dg)] + lpBuffer->SQR[abs(db)];
  719.     
  720.     if(dist < min_dist)
  721.     {
  722.      ptr->index = c; 
  723.      min_dist = dist;
  724.     }
  725.    }
  726.    bReturn = ptr->index;
  727.   }
  728.  return bReturn;
  729. }
  730.  
  731.  
  732. ///////////////////////////////////////////////////////////////////////////
  733. //
  734. void __export jitter(long x, long y, int *r,int *g,int *b)
  735. {
  736.  int p,q;
  737.  int tmp;
  738.  
  739.  tmp = *r;
  740.  if(tmp < 248)
  741.  {
  742.   p = tmp & 7;
  743.   q = jitterx(x,y,0);
  744.   if(p <= q)
  745.    tmp += 8;
  746.    
  747.   q = tmp + jittery(x,y,0);
  748.   if(q >= 0 && q <= 255)
  749.    tmp = q;
  750.   
  751.   *r = tmp & 0xF8;
  752.   }
  753.   
  754.  tmp = *g;
  755.  if(tmp < 248)
  756.  {
  757.   p = tmp & 7;
  758.   q = jitterx(x,y,1);
  759.   if(p <= q)
  760.    tmp += 8;
  761.    
  762.   q = tmp + jittery(x,y,1);
  763.   if(q >= 0 && q <= 255)
  764.    tmp = q;
  765.   
  766.   *g = tmp & 0xF8;
  767.   } 
  768.   
  769.  tmp = *b;
  770.  if(tmp < 248)
  771.  {
  772.   p = tmp & 7;
  773.   q = jitterx(x,y,2);
  774.   if(p <= q)
  775.    tmp += 8;
  776.    
  777.   q = tmp + jittery(x,y,2);
  778.   if(q >= 0 && q <= 255)
  779.    tmp = q;
  780.   
  781.   *b = tmp & 0xF8;
  782.   }
  783. }
  784.  
  785. ///////////////////////////////////////////////////////////////////////////
  786. // 
  787. void __export LoadDefaultPal(LPQUANT_BUFFER lpBuffer)
  788. {
  789.  int *ptr = def_pal; 
  790.  int i;
  791.  
  792.  for(i=0;i<256;i++)
  793.  {
  794.   lpBuffer->red[i] = *ptr++;
  795.   lpBuffer->green[i] = *ptr++;
  796.   lpBuffer->blue[i] = *ptr++; 
  797.  }
  798. }
  799. ///////////////////////////////////////////////////////////////////////////
  800. // 
  801. LPSTR FAR FindDIBBits(LPSTR lpDIB)
  802. {
  803.    return (lpDIB + *(LPDWORD)lpDIB + PaletteSize(lpDIB));
  804. }
  805.  
  806. ///////////////////////////////////////////////////////////////////////////
  807. // 
  808. WORD FAR PaletteSize(LPSTR lpDIB)
  809. {
  810.    /* calculate the size required by the palette */
  811.    if (IS_WIN30_DIB (lpDIB))
  812.       return (DIBNumColors(lpDIB) * sizeof(RGBQUAD));
  813.    else
  814.       return (DIBNumColors(lpDIB) * sizeof(RGBTRIPLE));
  815. }
  816.  
  817. ///////////////////////////////////////////////////////////////////////////
  818. // 
  819. WORD FAR DIBNumColors(LPSTR lpDIB)
  820. {
  821.    WORD wBitCount;  // DIB bit count
  822.  
  823.    /*  If this is a Windows-style DIB, the number of colors in the
  824.     *  color table can be less than the number of bits per pixel
  825.     *  allows for (i.e. lpbi->biClrUsed can be set to some value).
  826.     *  If this is the case, return the appropriate value.
  827.     */
  828.  
  829.    if (IS_WIN30_DIB(lpDIB))
  830.    {
  831.       DWORD dwClrUsed;
  832.  
  833.       dwClrUsed = ((LPBITMAPINFOHEADER)lpDIB)->biClrUsed;
  834.       if (dwClrUsed)
  835.      return (WORD)dwClrUsed;
  836.    }
  837.  
  838.    /*  Calculate the number of colors in the color table based on
  839.     *  the number of bits per pixel for the DIB.
  840.     */
  841.    if (IS_WIN30_DIB(lpDIB))
  842.       wBitCount = ((LPBITMAPINFOHEADER)lpDIB)->biBitCount;
  843.    else
  844.       wBitCount = ((LPBITMAPCOREHEADER)lpDIB)->bcBitCount;
  845.  
  846.    /* return number of colors based on bits per pixel */
  847.    switch (wBitCount)
  848.       {
  849.    case 1:
  850.       return 2;
  851.  
  852.    case 4:
  853.       return 16;
  854.  
  855.    case 8:
  856.       return 256;
  857.  
  858.    default:
  859.       return 0;
  860.       }
  861. }
  862.  
  863.